package com.wind.utils.cipher;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;


/**
 * <p>
 *  AES（Advanced Encryption Standard）
 * 历史：AES是在2001年由美国国家标准局（NIST）采纳为标准的，用以取代DES。
 * 密钥长度：AES支持128、192和256位密钥长度，提供了更高的安全性。
 * 安全性：AES被认为是非常安全的，目前还没有已知的实用方法可以在合理时间内破解AES加密。
 * 模式：AES也可以以多种模式运行，包括ECB、CBC、CFB以及更高级的模式如CTR（计数器模式）和GCM（伽罗瓦/计数器模式）。
 * </p>
 * @author wind
 * @date    2024-12-10 16:24
 * @version v1.0
 */
public class AesUtil {

    private static final String AES_KEY = "AES";

    /**
     * des加密
     * @param str 待加密对象
     * @param key 密钥 长度为8的倍数
     * @return
     */
    public static byte[] encrypt(String str, String key) {
        byte[] bytes = null;

        try {
            Cipher cipher = init(Cipher.ENCRYPT_MODE, key);
            bytes = cipher.doFinal(str.getBytes(StandardCharsets.UTF_8));
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        return bytes;
    }

    /**
     * des解密
     * @param bytes 待解密对象
     * @param key 密钥 长度为8的倍数
     * @return
     */
    public static String decrypt(byte[] bytes,String key) {
        String str = null;
        try {
            Cipher cipher = init(Cipher.DECRYPT_MODE, key);
            str = new String(cipher.doFinal(bytes), StandardCharsets.UTF_8);
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }

        return str;
    }


    /**
     * 初始化
     * @param mode
     * @param key
     * @return
     */
    private static Cipher init(int mode, String key){
        Cipher cipher = null;
        try {
            KeyGenerator kGen = KeyGenerator.getInstance(AES_KEY);

            kGen.init(128, new SecureRandom(key.getBytes()));

            cipher = Cipher.getInstance(AES_KEY);
            cipher.init(mode, new SecretKeySpec(kGen.generateKey().getEncoded(), AES_KEY));

        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return cipher;
    }
}
